/*
SandBox2D - Tools and Middleware 2011/2012 Assignment 1  - Sam Latif MA002HA

A heavily modified testbed, with added runtime shape creation/editing, FMOD sounds and XML meta data save/load functionality

Ball.h - Contains our Ball shape class and method declarations
*/

#ifndef BALL_H_
#define BALL_H_

class Ball
{
private:
 
	b2Body* ball_;

	int bodyType_;
	int fixedRotation_;
	float radius_;
	b2Vec2 position_;
	float angle_;
	float mass_;
	float restitution_;
	float friction_;
	float velocityX_;
	float velocityY_;
	float angularVelocity_;
public:
	//constructor
	Ball(): bodyType_(0), fixedRotation_(0), position_(0,0), angle_(0), mass_(0.0f), radius_(0.0f), restitution_(0.0f), friction_(0.0f), velocityX_(0.0f), velocityY_(0.0f), angularVelocity_(0.0f) {}
	
	// return shape attribute methods
	b2Body* getBody() {return ball_;}

	int getBodyType() {return bodyType_;}

	int getFixRotation() {return fixedRotation_;}

	float getRadius() {return radius_;}

	b2Vec2 getPosition() {return position_;}

	float getAngle() {return angle_;}

	float getMass() {return mass_;}

	float getRestitution() {return restitution_;}

	float getFriction()	{return friction_;}

	float getVelocityX() {return velocityX_;}

	float getVelocityY() {return velocityY_;}

	float getAngularVelocity() {return angularVelocity_;}
	
	static const char *typeName() {return "Ball";}
  
	// set new box attributes
	void newUserGeneratedBall(int bodyType, int fixedRotation, float radius, b2Vec2 position, float angle, float density, float restitution, float friction, b2Vec2 linearVelocity, float angularVelocity)
	{
		bodyType_ = bodyType;
		fixedRotation_ = fixedRotation;
		radius_ = radius;
		position_ = position;
		angle_ = angle;
		mass_ = density;
		restitution_ = restitution;
		friction_ = friction;
		velocityX_ = linearVelocity.x;
		velocityY_ = linearVelocity.y;
		angularVelocity_ = angularVelocity;
	}

	/// metadata: the contents of our class
	void meta(GsgMeta &meta)
	{
		meta.attr("getBodyType", bodyType_);
		meta.attr("getFixedRotation", fixedRotation_);
		meta.attr("getRadius", radius_);
		meta.attr("X", position_.x);
		meta.attr("Y", position_.y);
		meta.attr("getAngle", angle_);
		meta.attr("getMass", mass_);
		meta.attr("getRestitution", restitution_);
		meta.attr("getFriction", friction_);
		meta.attr("getVelocityX", velocityX_);
		meta.attr("getVelocityY", velocityY_);
		meta.attr("getAngularVelocity", angularVelocity_);
	}
	
	// load shape to world
	void addToWorld(b2World* world)
	{
		b2CircleShape shape;
		shape.m_radius = radius_;

		b2BodyDef body;

		switch(bodyType_)
		{
		case 0:
			{
				body.type = b2_staticBody;
			}
			break;
		case 1:
			{
				body.type = b2_dynamicBody;
			}
			break;
		case 2:
			{
				body.type = b2_kinematicBody;
			}
			break;
		}

		body.position.Set(position_.x, position_.y);
		body.angle = angle_;
		body.fixedRotation = fixedRotation_ > 0 ? 1 : 0;
		body.linearVelocity = b2Vec2(velocityX_, velocityY_);
		body.angularVelocity = angularVelocity_;
		ball_ = world->CreateBody(&body);

		b2FixtureDef fixDef;
		fixDef.shape = &shape;
		fixDef.density = mass_;
		fixDef.restitution = restitution_;

		ball_->CreateFixture(&fixDef);
	}

	//grab and save current position and velocities of shape
	void saveShape()
	{
		position_.Set(ball_->GetPosition().x, ball_->GetPosition().y);
		angle_	= ball_->GetAngle();
		velocityX_ = ball_->GetLinearVelocity().x;
		velocityY_ = ball_->GetLinearVelocity().y;
		angularVelocity_ = ball_->GetAngularVelocity();
	}

};

#endif